package com.xsf.jieyou.business.controller;

import com.xsf.jieyou.business.BusinessException;
import com.xsf.jieyou.business.common.dto.ResponseResult;
import com.xsf.jieyou.business.common.dto.ResponseStatus;
import com.xsf.jieyou.business.dto.LoginParam;
import com.xsf.jieyou.business.service.LoginServiceImpl;
import com.xsf.jieyou.cloud.api.CloudRedisSmsService;
import com.xsf.jieyou.cloud.api.CloudSmsService;
import com.xsf.jieyou.cloud.dto.SmsParam;
import com.xsf.jieyou.commons.utils.RegexUtils;
import com.xsf.jieyou.provider.api.ProviderTbUserService;
import com.xsf.jieyou.provider.domain.TbUser;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * 短信快捷登录 控制层
 *
 * @author xsfno1
 * @version v1.0.0
 * @date 2020/3/11 16:24
 * @see com.xsf.jieyou.business.controller
 **/
@RestController
@RequestMapping("/user/phonelogin")
public class PhoneLoginController {
    @Reference(version = "1.0.0")
    private ProviderTbUserService providerTbUserService;
    @Reference(version = "1.0.0")
    private CloudRedisSmsService cloudRedisSmsService;
    @Reference(version = "1.0.0")
    private CloudSmsService cloudSmsService;
    @Resource
    private BCryptPasswordEncoder passwordEncoder;
    @Resource
    private LoginServiceImpl loginServiceImpl;

    /**
     * 发送短信成功返回信息   Message:OK
     */
    private static final String SMS_MESSAGE_SUCCESS = "OK";

    /**
     * 校验手机号是否存在(是否已注册)
     *
     * @param phone 手机号
     * @return {@link ResponseResult}
     */
    @PostMapping(value = "check/{phone}")
    public ResponseResult<?> validatePhoneNum(@PathVariable String phone) {
        // 1、格式验证，失败抛出自定义异常
        this.validatePhoneFormat(phone);
        // 2、存在性验证，失败抛出自定义异常
        this.validatePhoneIsExist(phone);
        // 3、通过
        return new ResponseResult(ResponseStatus.SUCCESS);
    }

    /**
     * 手机验证码验证 SUCCESS=>登录
     *
     * @param phone 手机号
     * @param code  验证码
     * @return {@link ResponseResult}
     */
    @PostMapping(value = "login/{phone}/{code}")
    public ResponseResult<?> checkPhoneCode(@PathVariable String phone, @PathVariable String code) {
        // 1、格式验证，失败抛出自定义异常
        this.validatePhoneFormat(phone);
        this.validatePhoneCodeFormat(code);

        // 2、账号存在性验证，失败抛出自定义异常
        this.validatePhoneIsExist(phone);

        // 3、手机验证码验证
        this.validatePhoneCode(phone, code);

        // 4、通过,执行无密码方式登录,完成oAuth2安全认证
        //4.1.查询用户对象
        TbUser condition = new TbUser();
        condition.setPhone(phone);
        TbUser tbUser = this.providerTbUserService.get(condition);
        //4.2.oAuth2安全认证
        if (tbUser != null) {
            //无密码登录方式,通过设置默认密码"12345678"完成登录认证
            return this.loginServiceImpl.login(new LoginParam("#" + tbUser.getUsername(), "12345678"));
        }

        return new ResponseResult(ResponseStatus.DEFEATED);
    }

    /**
     * 验证码发送
     *
     * @param phone 手机号
     */
    @PostMapping(value = "sms/{phone}")
    public ResponseResult sendRegisterSms(@PathVariable String phone) {
        // 1、格式验证，失败抛出自定义异常
        this.validatePhoneFormat(phone);
        // 2、唯一性验证，失败抛出自定义异常
        this.validatePhoneIsExist(phone);

        // 3、通过，发送SMS
        try {
            SmsParam smsParam = this.cloudSmsService.sendLoginSms(phone);
            if (smsParam != null) {
                if (SMS_MESSAGE_SUCCESS.equals(smsParam.getMessage())) {
                    return new ResponseResult(ResponseStatus.SUCCESS);
                }
                throw new BusinessException(ResponseStatus.SEND_SMS_ERROR, smsParam.getMessage());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        throw new BusinessException(ResponseStatus.SEND_SMS_ERROR);
    }

    /**
     * 校验手机号存在性
     *
     * @param phone 手机号
     */
    private void validatePhoneIsExist(String phone) {
        int count = this.providerTbUserService.validatePhoneNum(phone);
        if (count == 0) {
            // 用户不存在
            throw new BusinessException(ResponseStatus.ACCOUNT_NOT_EXIST);
        }
    }

    /**
     * 校验手机号格式
     *
     * @param phone 手机号
     */
    private void validatePhoneFormat(String phone) {
        if (StringUtils.isEmpty(phone) ||
                !RegexUtils.validatePhone(phone)
        ) {
            throw new BusinessException(ResponseStatus.REQUEST_PARAM_INVALID);
        }
    }

    /**
     * 验证码验证
     *
     * @param phone 手机号
     * @param code  验证码
     */
    private void validatePhoneCode(String phone, String code) {
        // 获取Redis中的验证码（加密后的）
        String redisCode = this.cloudRedisSmsService.selectLoginCodeFromRedis(phone);
        // 验证码比较
        boolean matches = this.passwordEncoder.matches(code, redisCode);
        // 失败，抛出自定义异常
        if (!matches) {
            throw new BusinessException(ResponseStatus.AUTH_CODE_ERROR);
        }
    }

    /**
     * 校验验证码格式
     *
     * @param code 验证码
     */
    private void validatePhoneCodeFormat(String code) {
        if (StringUtils.isEmpty(code) ||
                !RegexUtils.validatePhoneCode(code)
        ) {
            throw new BusinessException(ResponseStatus.REQUEST_PARAM_INVALID);
        }
    }
}
